
/*
 * Public Credit Information Sharing Platform(PCISP).
 * Copyright (c) 2019-2020 jsxzkingdee and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 * Please visit https://www.zhengxinsoft.com if you need additional information or have any questions.
 */
package com.platform.comm.util;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.stereotype.Component;

import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.Map;

/**
 * Spring 工具类
 *
 * @author libin
 */
@Slf4j
@Component
@SuppressWarnings("unused")
public class SpringBeansUtil implements ApplicationContextAware, DisposableBean {
    private static ApplicationContext context;

    @Override
    public void setApplicationContext(@Nonnull ApplicationContext ac) throws BeansException {
        log.warn("## SpringBeanUtil::setApplicationContext ## " + ac);
        context = ac;
    }

    public static Class<?> getType(String name) throws BeansException {
        return context.getType(name);
    }

    public static Object getBean(String name) throws NoSuchBeanDefinitionException {
        return context.getBean(name);
    }

    public static Object getBeanSafe(String name) {
        try {
            return context.getBean(name);
        } catch (NoSuchBeanDefinitionException | NullPointerException e) {
            return null;
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBean(Class<T> clazz, String name) throws NoSuchBeanDefinitionException {
        return ((T) context.getBean(name));
    }

    @SuppressWarnings("unchecked")
    public static <T> T getBeanSafe(Class<T> clazz, String name) {
        try {
            if (context != null) {
                Object bean = context.getBean(name);
                return clazz.isInstance(bean) ? (T) bean : null;
            }
        } catch (NoSuchBeanDefinitionException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public static <T> T getBeanSafe(Class<T> clazz) {
        try {
            if (context != null) {
                return context.getBean(clazz);
            }
        } catch (NoSuchBeanDefinitionException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    public static <T> T getBean(Class<T> clazz) {
        if (context != null) {
            return context.getBean(clazz);
        }
        return null;
    }

    public static <T> Map<String, T> getBeans(Class<T> clazz) {
        if (context != null) {
            return context.getBeansOfType(clazz);
        }
        return new HashMap<>(0);


    }

    /**
     * 发布事件
     *
     * @param event 事件
     */
    public static <T extends ApplicationEvent> void publishEvent(T event) {
        if (context == null) {
            return;
        }
        context.publishEvent(event);
    }

    public static ApplicationContext getContext() {
        return context;
    }

    /**
     * 清除SpringBeanUtil中的ApplicationContext为Null.
     */
    public static void clearHolder() {
        if (log.isDebugEnabled()) {
            log.debug("清除SpringBeanUtil中的ApplicationContext:" + context);
        }
        context = null;
    }

    /**
     * 实现DisposableBean接口, 在Context关闭时清理静态变量.
     */
    @SneakyThrows
    @Override
    public void destroy() {
        SpringBeansUtil.clearHolder();
    }
}
